"""
文件名: dependencies.py
描述: FastAPI依赖注入模块

本模块包含以下主要功能：
1. 用户认证依赖
2. 权限验证依赖
3. 数据库会话依赖
4. 服务实例依赖
5. 分页参数依赖

依赖模块:
   - fastapi: Web框架依赖注入
   - sqlalchemy: 数据库会话
   - services: 各种服务类

使用示例:
   >>> @app.get("/protected")
   >>> async def protected_route(
   ...     current_user: User = Depends(get_current_user),
   ...     db: AsyncSession = Depends(get_db)
   ... ):
   ...     return {"user": current_user}

注意事项:
   - 依赖注入要处理异常
   - 数据库会话要正确关闭
   - 权限验证要完整
   - 服务实例要单例化

作者: AI助手
创建日期: 2024-06-27
最后修改: 2024-06-27
版本: 1.0.0
"""

from typing import Optional, Dict, Any
import uuid

from fastapi import Depends, HTTPException, status, Query, Header
from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials
from sqlalchemy.ext.asyncio import AsyncSession

from src.core.database import get_db
from src.core.logger import get_logger
from src.models.user import User
from src.services import (
    AuthService,
    UserService,
    CategoryService,
    VideoService,
    SearchService,
    YouTubeService,
)
from src.utils.exceptions import (
    AuthenticationException,
    AuthorizationException,
    InvalidTokenException,
    TokenExpiredException,
)

logger = get_logger(__name__)

# HTTP Bearer token认证
security = HTTPBearer(auto_error=False)


async def get_auth_service() -> AuthService:
    """获取认证服务实例"""
    return AuthService()


async def get_user_service() -> UserService:
    """获取用户服务实例"""
    return UserService()


async def get_category_service() -> CategoryService:
    """获取分类服务实例"""
    return CategoryService()


async def get_video_service() -> VideoService:
    """获取视频服务实例"""
    return VideoService()


async def get_search_service() -> SearchService:
    """获取搜索服务实例"""
    return SearchService()


async def get_youtube_service() -> YouTubeService:
    """获取YouTube服务实例"""
    return YouTubeService()


async def get_current_user(
    credentials: Optional[HTTPAuthorizationCredentials] = Depends(security),
    auth_service: AuthService = Depends(get_auth_service),
) -> User:
    """
    获取当前认证用户
    
    Args:
        credentials: HTTP Bearer认证凭据
        auth_service: 认证服务
        
    Returns:
        User: 当前用户对象
        
    Raises:
        HTTPException: 认证失败时抛出
    """
    if not credentials:
        raise HTTPException(
            status_code=status.HTTP_401_UNAUTHORIZED,
            detail="未提供认证令牌",
            headers={"WWW-Authenticate": "Bearer"},
        )
    
    try:
        # 验证访问令牌
        token = credentials.credentials
        user = await auth_service.get_current_user(token)
        
        if not user:
            raise HTTPException(
                status_code=status.HTTP_401_UNAUTHORIZED,
                detail="无效的认证令牌",
                headers={"WWW-Authenticate": "Bearer"},
            )
        
        if not user.is_active:
            raise HTTPException(
                status_code=status.HTTP_403_FORBIDDEN,
                detail="用户账户已被禁用",
            )
        
        return user
        
    except (InvalidTokenException, TokenExpiredException) as e:
        raise HTTPException(
            status_code=status.HTTP_401_UNAUTHORIZED,
            detail=str(e),
            headers={"WWW-Authenticate": "Bearer"},
        )
    except Exception as e:
        logger.error(f"获取当前用户失败: {e}")
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail="认证服务错误",
        )


async def get_current_active_user(
    current_user: User = Depends(get_current_user),
) -> User:
    """
    获取当前活跃用户（已验证是否激活）
    
    Args:
        current_user: 当前用户
        
    Returns:
        User: 当前活跃用户
    """
    if not current_user.is_active:
        raise HTTPException(
            status_code=status.HTTP_403_FORBIDDEN,
            detail="用户账户未激活",
        )
    
    return current_user


async def get_optional_current_user(
    credentials: Optional[HTTPAuthorizationCredentials] = Depends(security),
    auth_service: AuthService = Depends(get_auth_service),
) -> Optional[User]:
    """
    获取可选的当前用户（用于可选认证的端点）
    
    Args:
        credentials: HTTP Bearer认证凭据
        auth_service: 认证服务
        
    Returns:
        Optional[User]: 当前用户对象，未认证时返回None
    """
    if not credentials:
        return None
    
    try:
        token = credentials.credentials
        user = await auth_service.get_current_user(token)
        return user if user and user.is_active else None
    except Exception:
        return None


def get_pagination_params(
    page: int = Query(1, ge=1, description="页码"),
    size: int = Query(20, ge=1, le=100, description="每页数量"),
) -> Dict[str, int]:
    """
    获取分页参数
    
    Args:
        page: 页码（从1开始）
        size: 每页数量（1-100）
        
    Returns:
        Dict[str, int]: 分页参数字典
    """
    return {
        "page": page,
        "size": size,
        "offset": (page - 1) * size,
        "limit": size,
    }


def get_search_params(
    q: Optional[str] = Query(None, description="搜索关键词"),
    sort: Optional[str] = Query("created_at", description="排序字段"),
    order: Optional[str] = Query("desc", regex="^(asc|desc)$", description="排序方向"),
) -> Dict[str, Any]:
    """
    获取搜索参数
    
    Args:
        q: 搜索关键词
        sort: 排序字段
        order: 排序方向
        
    Returns:
        Dict[str, Any]: 搜索参数字典
    """
    return {
        "query": q,
        "sort_by": sort,
        "sort_order": order,
    }


async def verify_category_owner(
    category_id: uuid.UUID,
    current_user: User = Depends(get_current_user),
    category_service: CategoryService = Depends(get_category_service),
) -> None:
    """
    验证分类所有权
    
    Args:
        category_id: 分类ID
        current_user: 当前用户
        category_service: 分类服务
        
    Raises:
        HTTPException: 权限不足时抛出
    """
    try:
        category = await category_service.get_category_by_id(category_id, current_user.id)
        if not category:
            raise HTTPException(
                status_code=status.HTTP_404_NOT_FOUND,
                detail="分类不存在",
            )
    except Exception as e:
        logger.error(f"验证分类所有权失败: {e}")
        raise HTTPException(
            status_code=status.HTTP_403_FORBIDDEN,
            detail="无权限访问该分类",
        )


async def get_rate_limit_info(
    x_forwarded_for: Optional[str] = Header(None),
    x_real_ip: Optional[str] = Header(None),
) -> Dict[str, str]:
    """
    获取速率限制相关信息
    
    Args:
        x_forwarded_for: 转发IP头
        x_real_ip: 真实IP头
        
    Returns:
        Dict[str, str]: 客户端信息
    """
    # 获取客户端IP
    client_ip = x_real_ip or x_forwarded_for or "unknown"
    if x_forwarded_for:
        # 取第一个IP（通常是真实客户端IP）
        client_ip = x_forwarded_for.split(",")[0].strip()
    
    return {
        "client_ip": client_ip,
        "forwarded_for": x_forwarded_for or "",
        "real_ip": x_real_ip or "",
    }


# 权限验证依赖
class PermissionChecker:
    """权限检查器"""
    
    def __init__(self, required_permission: str):
        self.required_permission = required_permission
    
    def __call__(self, current_user: User = Depends(get_current_user)) -> User:
        """
        检查用户权限
        
        Args:
            current_user: 当前用户
            
        Returns:
            User: 验证通过的用户
            
        Raises:
            HTTPException: 权限不足时抛出
        """
        # 这里可以根据具体需求实现权限检查逻辑
        # 例如检查用户角色、权限标志等
        
        if not current_user.is_active:
            raise HTTPException(
                status_code=status.HTTP_403_FORBIDDEN,
                detail="用户账户未激活",
            )
        
        # 示例：检查高级用户权限
        if self.required_permission == "premium" and not current_user.is_premium:
            raise HTTPException(
                status_code=status.HTTP_403_FORBIDDEN,
                detail="需要高级用户权限",
            )
        
        return current_user


# 常用权限检查器实例
require_premium = PermissionChecker("premium")
require_admin = PermissionChecker("admin")


# 服务健康检查依赖
async def check_service_health() -> Dict[str, str]:
    """
    检查服务健康状态
    
    Returns:
        Dict[str, str]: 健康状态信息
    """
    # 这里可以检查数据库、Redis、外部API等服务状态
    return {
        "status": "healthy",
        "timestamp": str(uuid.uuid4()),
    }


__all__ = [
    "get_auth_service",
    "get_user_service", 
    "get_category_service",
    "get_video_service",
    "get_search_service",
    "get_youtube_service",
    "get_current_user",
    "get_current_active_user",
    "get_optional_current_user",
    "get_pagination_params",
    "get_search_params",
    "verify_category_owner",
    "get_rate_limit_info",
    "PermissionChecker",
    "require_premium",
    "require_admin",
    "check_service_health",
]